home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume1 / roll < prev    next >
Encoding:
Text File  |  1987-06-30  |  10.7 KB  |  405 lines

  1. Path: uunet!ukma!rutgers!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games-request
  2. From: games-request@tekred.TEK.COM
  3. Newsgroups: comp.sources.games
  4. Subject: v01i066:  roll - automatic dice roller
  5. Message-ID: <1356@tekred.TEK.COM>
  6. Date: 29 Jun 87 23:47:13 GMT
  7. Expires: 29 Jul 87 23:45:54 GMT
  8. Sender: billr@tekred.TEK.COM
  9. Lines: 393
  10. Approved: billr@tekred.TEK.COM
  11.  
  12. Submitted by: Bruce Holloway <drivax!holloway@ames.arpa>
  13. Comp.sources.games: Volume 1, Issue 66
  14. Archive-name: roll
  15.  
  16.     [I haven't tried this, so you're on your own.  -br]
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of shell archive."
  25. # Contents:  README Makefile roll.c
  26. # Wrapped by billr@tekred on Mon Jun 29 16:37:32 1987
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f README -a "${1}" != "-c" ; then 
  29.   echo shar: Will not over-write existing file \"README\"
  30. else
  31. echo shar: Extracting \"README\" \(985 characters\)
  32. sed "s/^X//" >README <<'END_OF_README'
  33. XThe Ultimate Dice Roller! Should be transportable to most systems that
  34. Xcan run 'C' and have the standard library.
  35. X
  36. XThis dice roller is random, even if the random number generator isn't very
  37. Xrandom.
  38. X
  39. XUsage: (options included in braces):
  40. X
  41. Xroll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides}
  42. X
  43. Xnumrep   [1]       = number of times to repeat the rolling sequence.
  44. Xbestroll [numroll] = print the best "bestroll" rolls.
  45. Xnumroll  [1]       = number of rolls to do.
  46. Xbestdice [numdice] = use the "bestdice" highest rolling dice.
  47. Xnumdice  [1]       = number of dice to use per roll.
  48. Xsides    [100]     = number of sides on the dice.
  49. X
  50. XExamples:
  51. X    roll
  52. X        d100 = 65 
  53. X    roll 6
  54. X        d6 = 3 
  55. X    roll 4d10
  56. X        4d10 = 11 
  57. X    roll 5,10d8
  58. X        5,10d8 = 28 
  59. X    roll 6x3d6
  60. X        6x3d6 = 17 12 11 11 10 6 
  61. X    roll 6x3,4d6
  62. X        6x3,4d6 = 18 15 10 10 7 6 
  63. X    roll 5,10x4d4
  64. X        5,10x4d4 = 14 13 12 12 10 
  65. X    roll 3@6,10x3,4d6
  66. X        6,10x3,4d6 = 17 17 15 15 14 14 
  67. X        6,10x3,4d6 = 18 15 15 15 14 14 
  68. X        6,10x3,4d6 = 16 14 13 13 11 11 
  69. X
  70. END_OF_README
  71. if test 985 -ne `wc -c <README`; then
  72.     echo shar: \"README\" unpacked with wrong size!
  73. fi
  74. # end of overwriting check
  75. fi
  76. if test -f Makefile -a "${1}" != "-c" ; then 
  77.   echo shar: Will not over-write existing file \"Makefile\"
  78. else
  79. echo shar: Extracting \"Makefile\" \(229 characters\)
  80. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  81. X#    Makefile for ROLL
  82. X#
  83. X#    Comment out the BSD line if you're on System V
  84. X#    Comment out the SYSV line if you're using Berkely Unix.
  85. X
  86. X# SYSTEM = -DSYSV
  87. XSYSTEM = -DBSD
  88. X
  89. XCFLAGS = -O $(SYSTEM)
  90. X
  91. Xroll:    roll.c
  92. X    cc -o roll $(CFLAGS) roll.c
  93. END_OF_Makefile
  94. if test 229 -ne `wc -c <Makefile`; then
  95.     echo shar: \"Makefile\" unpacked with wrong size!
  96. fi
  97. # end of overwriting check
  98. fi
  99. if test -f roll.c -a "${1}" != "-c" ; then 
  100.   echo shar: Will not over-write existing file \"roll.c\"
  101. else
  102. echo shar: Extracting \"roll.c\" \(7305 characters\)
  103. sed "s/^X//" >roll.c <<'END_OF_roll.c'
  104. X/*****************************************************************************
  105. X*    ROLL - Rolls dice - lots of them - and really randomly.
  106. X*
  107. X*
  108. X*    Usage: (options included in braces):
  109. X*
  110. X*    roll {numrep@}{{bestroll,}numroll x}{{bestdice,}numdice d}{sides}
  111. X*
  112. X*    numrep   [1]       = number of times to repeat the rolling sequence.
  113. X*    bestroll [numroll] = print the best "bestroll" rolls.
  114. X*    numroll  [1]       = number of rolls to do.
  115. X*    bestdice [numdice] = use the "bestdice" highest rolling dice.
  116. X*    numdice  [1]       = number of dice to use per roll.
  117. X*    sides    [100]     = number of sides on the dice.
  118. X*
  119. X*    Examples:
  120. X*        roll
  121. X*            d100 = 65 
  122. X*        roll 6
  123. X*            d6 = 3 
  124. X*        roll 4d10
  125. X*            4d10 = 11 
  126. X*        roll 5,10d8
  127. X*            5,10d8 = 28 
  128. X*        roll 6x3d6
  129. X*            6x3d6 = 17 12 11 11 10 6 
  130. X*        roll 6x3,4d6
  131. X*            6x3,4d6 = 18 15 10 10 7 6 
  132. X*        roll 5,10x4d4
  133. X*            5,10x4d4 = 14 13 12 12 10 
  134. X*        roll 3@6,10x3,4d6
  135. X*            6,10x3,4d6 = 17 17 15 15 14 14 
  136. X*            6,10x3,4d6 = 18 15 15 15 14 14 
  137. X*            6,10x3,4d6 = 16 14 13 13 11 11 
  138. X******************************************************************************/
  139. X
  140. X#include <stdio.h>
  141. X#include <ctype.h>
  142. X
  143. X#define    NUMREDUX    5
  144. X
  145. X#ifdef SYSV
  146. X#define    index    strchr
  147. X#define    rindex    strrchr
  148. X#define    srandom    srand
  149. X#define    random    rand
  150. X#endif
  151. X
  152. Xextern char *index(), *rindex();
  153. Xextern char *malloc();
  154. Xextern void free();
  155. X
  156. Xint numroll = 1, bestroll = 1;        /* Number of rolls to roll and keep */
  157. Xint numdice = 1, bestdice = 1;        /* Number of dice to roll and keep */
  158. Xint sides = 100;            /* Number of sides on each die */
  159. X
  160. Xint *ar_rolls;                /* Array of rolls */
  161. Xint *ar_dice;                /* Array of dice */
  162. Xint *ar_side;                /* Array of side data */
  163. X
  164. Xchar *show();                /* Routine to format output */
  165. X
  166. Xchar iline[80];                /* To parse the roll */
  167. Xchar aroll[80];                /* When rolls are repeated */
  168. X
  169. Xmain(acnt,avar)
  170. Xint acnt;
  171. Xchar *avar[];
  172. X{
  173. X    int i, j, k, val;
  174. X    char *s, *s1;
  175. X
  176. X/*    if(acnt < 2){
  177. X    printf("usage: roll {numroll x }{numdice d }{numsides}\n");
  178. X    printf("\tExample: roll 100 ; roll 3d8 ; roll 6x3d8\n");
  179. X    return;
  180. X    }
  181. X*/
  182. X    srandom(time(0L));            /* Randomize */
  183. X
  184. X    if(acnt <= 1)            /* Default: Roll 1d100 */
  185. X    roll("");
  186. X    else
  187. X    for(i=0; ++i < acnt;){        /* For each argument */
  188. X        s = avar[i];
  189. X        if(s1 = index(s,'@')){    /* Repeat the roll? */
  190. X        *s1 = 0;
  191. X        j = atoi(s);        /* Get repetition */
  192. X        if(j < 1){
  193. X            printf("roll: Repetition count must be greater than zero.\n");
  194. X            return;
  195. X            }
  196. X        s = s1+1;        /* Advance pointer past it */
  197. X        }
  198. X        else j = 1;            /* Default: Only one time. */
  199. X        strcpy(aroll,s);        /* Save it. */
  200. X        while(j--){
  201. X        strcpy(s,aroll);
  202. X        roll(s);        /* Do the roll */
  203. X        }
  204. X        }
  205. X}
  206. X
  207. Xroll(inline)
  208. Xchar *inline;
  209. X{
  210. X    int i, j, k, val, r;
  211. X    char *s, *s1;
  212. X
  213. X    numroll = bestroll = bestdice = numdice = 1; /* Set defaults. */
  214. X    sides = 100;
  215. X
  216. X    for(s=inline; *s; ++s)            /* Convert to lower case */
  217. X    if(isupper(*s))
  218. X        *s = tolower(*s);
  219. X
  220. X    s = inline;
  221. X    if(s1 = index(s,'x')){            /* Get number of rolls */
  222. X    *s1 = 0;
  223. X    parse(s,&numroll,&bestroll);
  224. X    s = s1+1;
  225. X    }
  226. X    if(s1 = index(s,'d')){            /* Get number of dice */
  227. X    *s1 = 0;
  228. X    parse(s,&numdice,&bestdice);
  229. X    s = s1+1;
  230. X    }
  231. X    if(*s) sides = atoi(s);            /* get number of sides */
  232. X
  233. X    if(error()) return;                /* Check sanity */
  234. X
  235. X    if(numroll > 1) printf("%sx",show(iline,bestroll,numroll));
  236. X    if(numdice > 1) printf("%s",show(iline,bestdice,numdice));
  237. X    printf("d%d = ",sides);
  238. X    fflush(stdout);                /* Echo the command */
  239. X
  240. X/* Allocate the arrays - one to keep all the rolls, one to keep each roll
  241. X   by the die roll, and one to make sure the dice are rolled RANDOMLY.
  242. X*/
  243. X    ar_rolls = (int *)malloc(sizeof(int) * numroll);
  244. X    ar_dice = (int *)malloc(sizeof(int) * numdice);
  245. X    ar_side = (int *)malloc(sizeof(int) * NUMREDUX * sides);
  246. X
  247. X/* Get out if we couldn't allocate the arrays */
  248. X
  249. X    if(!ar_rolls || !ar_dice || !ar_side){
  250. X    printf("*** Out of memory ***\n");
  251. X    if(ar_rolls) free(ar_rolls);
  252. X    if(ar_dice) free(ar_dice);
  253. X    if(ar_side) free(ar_side);
  254. X    return;
  255. X    }
  256. X
  257. X/* Make an array filled with the possible side values. Several times. So
  258. X   that even if the random number generator isn't completely random, it
  259. X   has a chance to produce random values when indexing into the array.
  260. X*/
  261. X    for(i=j=0; i<NUMREDUX; ++i)
  262. X    for(k=0; k++ < sides; ++j)
  263. X        *(ar_side+j) = k;
  264. X
  265. X/* Randomize the array - necessary to catch cyclic random number generators. */
  266. X
  267. X    for(i=0; i < NUMREDUX * sides; ++i){
  268. X    r = random();
  269. X    if(r < 0) r = -r;
  270. X    r %= NUMREDUX * sides;
  271. X    j = *(ar_side+i);
  272. X    *(ar_side+i) = *(ar_side+r);
  273. X    *(ar_side+r) = j;
  274. X    }
  275. X
  276. X    for(i = 0; i<numroll; ++i){            /* For each roll */
  277. X    for(j=0; j<numdice; ++j){        /* For each die */
  278. X        r = random();            /* Roll the die */
  279. X        if(r < 0) r = -r;
  280. X        *(ar_dice+j) = *(ar_side + (r % (sides * NUMREDUX)));
  281. X        }
  282. X    if(bestdice < numdice) sort(ar_dice,numdice); /* Get the best 'n' */
  283. X    for(j=val=0; j<bestdice; ++j)        /* Sum them to get the roll */
  284. X        val += *(ar_dice+j);
  285. X    *(ar_rolls+i) = val;
  286. X    }
  287. X    sort(ar_rolls,numroll);            /* Sort the rolls */
  288. X    for(i=0; i<bestroll; ++i)            /* And print out the best 'n' */
  289. X    printf("%d ",*(ar_rolls+i));
  290. X    printf("\n");
  291. X
  292. X    free(ar_rolls);                /* Free all the arrays */
  293. X    free(ar_dice);
  294. X    free(ar_side);
  295. X}
  296. X
  297. X/*****************************************************************************
  298. X*    PARSE
  299. X*
  300. X*    Figure out strings that look like "ddd" and "ddd,ddd", and fill in
  301. X*    the values nicely. Handle defaults, too.
  302. X******************************************************************************/
  303. X
  304. Xparse(s,n,b)
  305. Xchar *s;
  306. Xint *n, *b;
  307. X{
  308. X    char *s1;
  309. X
  310. X    if(s1 = index(s,',')){
  311. X    *s1 = 0;
  312. X    *b = atoi(s);
  313. X    *n = atoi(s1+1);
  314. X    }
  315. X    else *b = *n = atoi(s);
  316. X}
  317. X
  318. X/*****************************************************************************
  319. X*    SORT
  320. X*
  321. X*    Bubble sort (yech) an array.
  322. X******************************************************************************/
  323. X
  324. Xsort(a,n)
  325. Xint a[], n;
  326. X{
  327. X    int changed, i, t;
  328. X
  329. X    if(n <= 1) return;
  330. X
  331. X    for(changed=1; changed;){
  332. X    changed = 0;
  333. X    for(i=0; i<n-1; ++i){
  334. X        if(a[i] < a[i+1]){
  335. X        changed = 1;
  336. X        t = a[i]; a[i] = a[i+1]; a[i+1] = t;
  337. X        }
  338. X        }
  339. X    }
  340. X}
  341. X
  342. X/*****************************************************************************
  343. X*    ERROR
  344. X*
  345. X*    Scan and report any errors.
  346. X******************************************************************************/
  347. X
  348. Xerror(){
  349. X    int iserr=0;
  350. X
  351. X    if(numroll <= 0){
  352. X    fprintf(stderr,"roll: Number of rolls must be greater than zero.\n");
  353. X    ++iserr;
  354. X    }
  355. X
  356. X    if(bestroll < 1 || bestroll > numroll){
  357. X    fprintf(stderr,"roll: Number of rolls to keep must be greater than zero,\n");
  358. X    fprintf(stderr,"      less than the total number of rolls.\n");
  359. X    ++iserr;
  360. X    }
  361. X
  362. X    if(numdice <= 0){
  363. X    fprintf(stderr,"roll: Number of dice to roll must be greater than zero.\n");
  364. X    ++iserr;
  365. X    }
  366. X
  367. X    if(bestdice < 1 || bestdice > numdice){
  368. X    fprintf(stderr,"roll: Number of dice to keep must be greater than zero,\n");
  369. X    fprintf(stderr,"      less than the number of dice.\n");
  370. X    ++iserr;
  371. X    }
  372. X
  373. X    if(sides <= 1){
  374. X    fprintf(stderr,"roll: Dice must have at least two sides.\n");
  375. X    ++iserr;
  376. X    }
  377. X
  378. X    return(iserr);
  379. X}
  380. X
  381. X/*****************************************************************************
  382. X*    SHOW
  383. X*
  384. X*    Format some output.
  385. X******************************************************************************/
  386. X
  387. Xchar *show(s,b,n)
  388. Xchar *s;
  389. Xint b, n;
  390. X{
  391. X    if(b == n)
  392. X    sprintf(s,"%d",n);
  393. X    else
  394. X    sprintf(s,"%d,%d",b,n);
  395. X    return(s);
  396. X}
  397. END_OF_roll.c
  398. if test 7305 -ne `wc -c <roll.c`; then
  399.     echo shar: \"roll.c\" unpacked with wrong size!
  400. fi
  401. # end of overwriting check
  402. fi
  403. echo shar: End of shell archive.
  404. exit 0
  405.